/*******************************************************************************
 * SVN­Versioning-Information:
 * ­­­­­­­­­­­­­­­­­­­­­­­­
 * $LastChangedRevision: 6 $
 * $LastChangedBy: c.a.duevel $
 * $LastChangedDate: 2009-08-26 15:12:37 +0000 (Wed, 26 Aug 2009) $
 * $HeadURL: http://robofight.googlecode.com/svn/trunk/Server/src/de/hft_stuttgart/botwar/server/remote/RemotePlayer.java $
 ******************************************************************************/
package de.hft_stuttgart.botwar.server.remote;

import de.hft_stuttgart.botwar.common.commands.ChatCmd;
import de.hft_stuttgart.botwar.common.models.ArmamentInfo;
import de.hft_stuttgart.botwar.common.models.GameInfo;
import de.hft_stuttgart.botwar.common.commands.Cmd;
import de.hft_stuttgart.botwar.common.commands.KickCmd;
import de.hft_stuttgart.botwar.common.interfaces.IRemotePlayer;
import de.hft_stuttgart.botwar.common.models.ChassisInfo;
import de.hft_stuttgart.botwar.common.models.MapInfo;
import de.hft_stuttgart.botwar.common.models.NewRobotInfo;
import de.hft_stuttgart.botwar.common.models.PlayerInfo;
import de.hft_stuttgart.botwar.common.models.Position;
import de.hft_stuttgart.botwar.common.models.RobotInfo;
import de.hft_stuttgart.botwar.common.models.ShieldInfo;
import de.hft_stuttgart.botwar.database.Player;
import de.hft_stuttgart.botwar.server.model.Ranking;
import de.hft_stuttgart.botwar.server.model.RobotConfiguration;
import de.hft_stuttgart.botwar.database.Statistic;
import de.hft_stuttgart.botwar.server.DataBase;
import de.hft_stuttgart.botwar.server.Main;
import de.hft_stuttgart.botwar.server.model.Armament;
import de.hft_stuttgart.botwar.server.model.Chassis;
import de.hft_stuttgart.botwar.server.model.Coinsystem;
import de.hft_stuttgart.botwar.server.model.Game;
import de.hft_stuttgart.botwar.server.model.GameMap;
import de.hft_stuttgart.botwar.server.model.Shield;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Vector;
import org.apache.log4j.Logger;

/**
 * This class is the primary object the client uses to interact with
 * the server.
 * @author c.a.duevel@gmail.com, sdegiorgi@gmail.com, pmv-mail@gmx.de
 */
public class RemotePlayer implements IRemotePlayer {

    private List<Cmd> commands = new Vector<Cmd>();
    private final Object COMMAND_MONITOR = new Object();
    Game game;
    private boolean ready = false;
    boolean readyToInitialize = false;
    static Logger logger = Logger.getLogger(RemotePlayer.class);
    private Calendar lastPoll = Calendar.getInstance();
    private Ranking ranking;
    private Player player;

    public RemotePlayer(Player player) {
        this.player = player;
        ranking = getRanking();
    }

    /**
     * Only for tests! Otherwise, do not use!
     * @param user_id
     * @param player
     * @param ranking
     * @deprecated
     */
    @Deprecated
    public RemotePlayer(final String user_id, final Ranking ranking) {
        this.player = new Player(user_id, "e-mail@e-mail.de", "password");
        this.ranking = ranking;
    }

    /**
     *
     * @return player instance of this RemotePlayer
     */
    public Player getPlayer() {
        return player;
    }

    /**
     *
     * @return <code>true</code> if this player is ready to initialize.
     */
    public boolean isReadyToInitialize() {
        return readyToInitialize;
    }

    /**
     *
     * @return ID of this player
     */
    public String getID() {
        return player.getUsername();
    }

    /**
     * @return last time the client has polled
     */
    public Calendar getLastPoll() {
        return lastPoll;
    }

    /**
     *@return actual game of this player
     *
     */
    public Game getGame() {
        return game;
    }

    /**
     * If this player plays a game, this must be assigned.
     * @param game the game the player plays right now
     */
    public void setGame(final Game game) {
        this.game = game;
    }

    /**
     * Finishes the game that this player is playing right now.
     */
    public void finishGame() {
        if (getPlayer().isPlaying()) {
            DataBase.get().gameFinished(getPlayer());
        }
        game = null;
        ready = false;
        readyToInitialize = false;
    }

    /**
     * Add a command to the list of commands for this robot.
     * @param cmd the command to add.
     */
    public void addCommand(final Cmd cmd) {
        synchronized (COMMAND_MONITOR) {
            commands.add(cmd);
        }
    }

    /**
     * Add a list of commands to the list of commands for this robot.
     * @param list of commands to add.
     */
    public void addCommandList(final List<Cmd> list) {
        synchronized (COMMAND_MONITOR) {
            commands.addAll(list);
        }
        logger.info(String.format("Player %s has now %d new commands in cache",
                this.getID(),
                list.size()));
    }

    /**
     * This method is called all the time during the game by the client,
     * in order to receive new command objects.
     * @return The list of commands a client has to follow
     * @throws java.rmi.RemoteException
     */
    public List<Cmd> poll() throws RemoteException {
        List<Cmd> commandsToSend;
        synchronized (COMMAND_MONITOR) {
            commandsToSend = commands;
            commands = new Vector<Cmd>();
        }
        lastPoll = Calendar.getInstance();
        logger.info(String.format("Player %s is polling the server:" +
                "Receives %d new commands", getID(), commandsToSend.size()));
        return commandsToSend;
    }

    /**
     * A client calls this method if he is ready to start the game
     * @throws java.rmi.RemoteException
     * @throws IllegalStateException if there is no initialized game yet.
     */
    public void ready() throws RemoteException {
        checkIfGameExists();
        if (!isReadyToInitialize()) {
            throw new IllegalStateException("Is not initialized yet");
        }
        logger.info(String.format("Player %s is ready to start the game!", getID()));
        ready = true;
        game.start();
    }

    /**
     *
     * @return state for this client
     */
    public boolean isReady() {
        return ready;
    }

    /**
     *
     * @param id ID of the robot.
     * @return The position of this robot
     * @throws java.rmi.RemoteException If the robot does not exist
     */
    public Position getPosition(final Integer id) throws RemoteException {
        checkIfGameExists();
        return game.getPosOfRobot(id);


    }

    /**
     *
     * @param RobotId The robot to move.
     * @param target The target to move to.
     * @throws java.rmi.RemoteException
     */
    public void setTarget(final Integer RobotId, final Position target) throws
            RemoteException {
        checkIfGameExists();
        game.setTarget(RobotId, target, getID());
    }

    /**
     * Set a robot in a certain mode.
     * @param RobotId The robot to set.
     * @param mode The choosen mode.
     * @throws java.rmi.RemoteException
     */
    public void setMode(final Integer RobotId, final MODE mode)
            throws RemoteException {
        checkIfGameExists();
        game.setMode(RobotId, mode, getID());

    }

    private void checkIfGameExists() throws IllegalStateException {
        if (game == null) {
            throw new IllegalStateException("There is no game yet!");
        }
    }

    /**
     * Logout from the server.
     * @throws java.rmi.RemoteException
     */
    public void logout() throws RemoteException {
        if (!this.getPlayer().isPlaying()) {
            logger.debug(String.format("Logout issued by %s", this.getID()));
            Login.logout(this);
        } else {
            throw new UnsupportedOperationException("Can't perform logout" +
                    " during a game");
        }
    }

    /**
     * Enter a game
     * @param GameId The id of the game to enter.
     * @return <code>true</code> if the player could connect to the game.
     * @throws java.rmi.RemoteException
     */
    public boolean enterGame(final Integer GameId) throws RemoteException {
        if (this.game != null) {
            throw new UnsupportedOperationException("You are already in a " +
                    "game - can't enter a new one");
        }
        if (Game.getGame(GameId).getNumConnectedPlayers() >=
                Game.getGame(GameId).getMaxPlayers()) {
            return false;
        }
        this.game = Game.getGame(GameId);
        game.addPlayer(this);
        this.addCommand(new ChatCmd(
                CHATTYPE.GAMELOBBY,
                Main.getSystemName(),
                "In a gamelobby you can also see, what users are writing in " +
                "the lobby."));
        this.addCommand(new ChatCmd(
                CHATTYPE.GAMELOBBY,
                Main.getSystemName(),
                "To chat back to the lobby enter \"/lobby:\" before your " +
                "message."));
        return true;
    }

    /**
     *
     * @param GameID The game one wants to get information about.
     * @return Info about that game.
     * @throws java.rmi.RemoteException
     */
    public GameInfo getGameInfo(final Integer GameID) throws RemoteException {
        return Game.getGameInfo(GameID);
    }

    /**
     *
     * @param obj The object to compare
     * @return <code>true</code> if that object is of type RemotePlayer and has
     * the same ID.
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final RemotePlayer other = (RemotePlayer) obj;
        if ((this.getID() == null) ? (other.getID() != null) : !this.getID().equals(other.getID())) {
            return false;
        }
        return true;
    }

    /**
     * 
     * @return hashcode of this instance.
     */
    @Override
    public int hashCode() {
        int hash = 3;
        hash = 89 * hash + (this.getID() != null ? this.getID().hashCode() : 0);
        return hash;
    }

    /**
     *
     * @return ID of the created game
     * @throws java.rmi.RemoteException
     * @deprecated Use other createGame method instead.
     */
    @Deprecated
    public Integer createGame() throws RemoteException {
        return Game.createGame(this);
    }

    /**
     * The more elaborate Edition of createGame.
     * @param gameName A title for the game, may sth like "metzelstube"
     * @param mapName A string holding a ID for the desired map
     * @param maxPlayers The maxNum of players in this game
     * @param maxBots The maxNum of bots PER player in this game
     * @param maxPlayerLevel The maxPlayerLevel requested for this game
     * @return ID of the created Game
     * @throws RemoteException
     */
    public Integer createGame(final String gameName, final String mapName,
            final int maxPlayers, final int maxBots, final int maxPlayerLevel)
            throws RemoteException {
        return Game.createGame(this, gameName, mapName, maxPlayers, maxBots,
                maxPlayerLevel);
    }

    /**
     * Returns a List of <code>GameInfo</code> objects about all games.
     * currently initializing and getting played on this server.
     * @return getGameInfos() infos of a game
     * @throws java.rmi.RemoteException
     */
    public List<GameInfo> getGameInfos() throws RemoteException {
        return Game.getGameInfos();
    }

    /**
     * The client calls this method if he has made all the configuration
     * for the game and is ready to prepare the start of the game.
     * @param robotList integer array containing an ordered list of desired bots
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public void readyToInit(final List<Integer> robotList) throws RemoteException {
        checkIfGameExists();
        if (!isReadyToInitialize()) {
            game.setPlayerRobots(this, robotList);
            readyToInitialize = true;
            game.init(getID());
        } else {
            throw new IllegalStateException("You have already initialized!");
        }
    }

    /**
     * This method can be called by client from anywhere within the application
     * after successful logon. Chat Messages can be either sent to lobby,
     * the gamelobby or to an individual player.
     * @throws java.rmi.RemoteException
     * @throws IllegalArgumentException
     */
    public void sendChatMsg(final CHATTYPE type, final String message,
            final String recipient) throws RemoteException, IllegalArgumentException {
        switch (type) {
            case LOBBY:
                if (!this.getPlayer().isPlaying()) {
                    for (RemotePlayer player : Login.loggedInPlayers()) {
                        if ((player.getGame() == null) ||
                                !player.getGame().isRunning()) {
                            player.addCommand(new ChatCmd(CHATTYPE.LOBBY,
                                    this.getID(), message));
                        }
                    }
                } else {
                    throw new IllegalArgumentException("You can't chat to " +
                            "Lobby while in a game.");
                }
                break;
            case GAMELOBBY:
                if (this.getGame() != null) {
                    for (RemotePlayer player : Login.loggedInPlayers()) {
                        if ((player.getGame() != null) &&
                                this.getGame().equals(player.getGame())) {
                            player.addCommand(new ChatCmd(CHATTYPE.GAMELOBBY,
                                    this.getID(), message));
                        }
                    }
                } else {
                    throw new IllegalArgumentException("You need to be in a " +
                            "game to use Gamechat.");
                }
                break;
            case PRIVATE:
                sendChatMsgPrivate(message, recipient);
                break;
        }
    }

    /**
     * This method can be called by client from anywhere within the application
     * after successful logon to send a private Chat Message.
     * @param message The message to be sent
     * @param recipient The recipient of the private chat message
     * @throws java.rmi.RemoteException
     * @throws IllegalArgumentException
     */
    public void sendChatMsgPrivate(final String message, final String recipientID)
            throws RemoteException, IllegalArgumentException {
        RemotePlayer recipient = Login.getPlayer(recipientID);
        if (recipient != null) {
            recipient.addCommand(
                    new ChatCmd(CHATTYPE.PRIVATE, this.getID(), message));
        } else {
            throw new IllegalArgumentException(String.format("Can't " +
                    "send chat to recipient %s - can't find player!",
                    recipientID));
        }
    }

    /**
     * This method can be called by client from lobby and gamelobby.
     * @return List of PlayerIDs
     * @throws java.rmi.RemoteException
     * @throws IllegalStateException
     */
    public List<String> getPlayerInfos()
            throws RemoteException, IllegalStateException {
        if ((this.getGame() != null) && this.getGame().isRunning()) {
            throw new IllegalStateException("You may not retrieve PlayerInfos " +
                    "while in a game.");
        }
        return Login.getLoggedInPlayerIDs();
    }

    /**
     * This method can be called by client from lobby and gamelobby.
     * @return List of PlayerIDs
     * @throws java.rmi.RemoteException
     * @throws IllegalStateException
     */
    public List<String> getPlayerInfos(final Integer gameID)
            throws RemoteException, IllegalStateException {

        if (this.getGame() == null) {
            throw new IllegalStateException("You are not in a game.");
        }
        if (this.getGame().isRunning()) {
            throw new IllegalStateException("Game is already running.");
        }

        List<String> playersInGameList = new ArrayList<String>();

        for (RemotePlayer rplayer : Login.loggedInPlayers()) {
            if (rplayer.getGame() != null &&
                    rplayer.getGame().getGameId().equals(gameID)) {


                playersInGameList.add(rplayer.getID());
            }
        }
        return playersInGameList;
    }

    /**
     * This method can be called by client from anywhere within the application.
     * @throws java.rmi.RemoteException
     */
    public PlayerInfo getPlayerInfo(final String playerID)
            throws RemoteException, IllegalArgumentException {
        boolean readyToInit = false;
        boolean isOnline = Login.isLoggedIn(playerID);
        int rank;
        Statistic stat = DataBase.get().getStatistic(playerID);
        long onlineTime = stat.getOnlineTime();

        if (isOnline) {
            RemotePlayer p = Login.getPlayer(playerID);
            readyToInit = p.isReadyToInitialize();
            rank = p.getRanking().getRank();
            onlineTime += p.getSessionTime();
        } else {
            rank = Ranking.get(playerID).getRank();
        }

        PlayerInfo info = new PlayerInfo(playerID,
                stat.getWonMatches(),
                stat.getLostMatches(),
                stat.getDrawMatches(),
                stat.getExperience(),
                rank,
                stat.getLastOnlineTime(),
                stat.getPlayingTime(),
                isOnline,
                onlineTime,
                Coinsystem.getLevelForCoins(stat.getExperience()),
                readyToInit);

        return info;
    }

    /**
     * Called by client to receive one statisticpage.
     * @param size size from one page
     * @param page the wanted pagenumber
     * @return getRankingPage list of PlayerInfo with all players
     * from the wanted page
     * @throws java.rmi.RemoteException
     */
    public List<PlayerInfo> getRankingPage(final int size, final int page) throws RemoteException {
        List<Ranking> rankList = Ranking.getPage(size, page);

        List<PlayerInfo> infoList = new ArrayList<PlayerInfo>(rankList.size());
        for (Ranking rank : rankList) {
            Statistic stat = DataBase.get().getStatistic(rank.getPlayerID());
            boolean isOnline = Login.isLoggedIn(stat.getPlayername());
            long onlineTime = stat.getOnlineTime();
            if (isOnline) {
                onlineTime +=
                        Login.getPlayer(rank.getPlayerID()).getSessionTime();
            }
            infoList.add(new PlayerInfo(stat.getPlayername(),
                    stat.getWonMatches(),
                    stat.getLostMatches(),
                    stat.getDrawMatches(),
                    rank.getCoins(),
                    rank.getRank(),
                    stat.getLastOnlineTime(),
                    stat.getPlayingTime(),
                    isOnline,
                    onlineTime,
                    Coinsystem.getLevelForCoins(rank.getCoins())));
        }

        return infoList;
    }

    /**
     * Called by client for shop.
     * @return list of all available chassises
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public List<ChassisInfo> getAvailableChassises() throws RemoteException {
        List<Chassis> chassisList = DataBase.get().getAvailableChassises(getLevelRank());
        List<ChassisInfo> infList = new ArrayList<ChassisInfo>();
        for (Chassis c : chassisList) {
            infList.add(c.getInfo());
        }
        return infList;

    }

    /**
     * Called by client for shop.
     * @return getAvailableShields list of all available shields
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public List<ShieldInfo> getAvailableShields() throws RemoteException {
        List<Shield> shieldList = DataBase.get().getAvailableShields(getLevelRank());
        List<ShieldInfo> infList = new ArrayList<ShieldInfo>();
        for (Shield c : shieldList) {
            infList.add(c.getInfo());
        }
        return infList;
    }

    /**
     * Called by client for shop
     * @return list of all available armaments
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public List<ArmamentInfo> getAvailableArmaments() throws RemoteException {
        List<Armament> armsList = DataBase.get().getAvailableArmaments(getLevelRank());
        List<ArmamentInfo> infList = new ArrayList<ArmamentInfo>();
        for (Armament c : armsList) {
            infList.add(c.getInfo());
        }
        return infList;
    }

    /**
     * Called by client for shop and befor gamestart.
     * @return getAvailableRobots list of all available (previous builded)
     * robots from player
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public List<RobotInfo> getAvailableRobots() throws RemoteException {
        if (this.getGame() == null) {
            //not in a game, get all robots
            return DataBase.get().getAvailableRobots(getID(), Coinsystem.getTopLevel());
        } else {
            //in a game, so robots with higher levels are not needed.
            return DataBase.get().getAvailableRobots(getID(), getGame().getMaxPlayerLevel());
        }
    }

    /**
     * Save a builded robot from player in db.
     * @param robot a builded robot
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public void saveRobot(final NewRobotInfo robot) throws RemoteException {
        DataBase.get().insertRobot(robot, getID());
    }

    /**
     * Remove a existing robot from this player.
     * @param robotId id from robot
     * @throws java.lang.IllegalArgumentException thrown if the robot does not
     * exist.
     */
    public void removeRobot(final int robotId)
            throws IllegalArgumentException,
            RemoteException {
        DataBase.get().deleteRobot(getID(), robotId);
    }

    /**
     * Called by (game-owner) client to remove a player from gameLobby
     * @param playerID The string representation of the player to be kicked
     * @return Boolean indicating whether kick was successful
     * @throws java.rmi.RemoteException throws RemoteException
     * @throws IllegalStateException If the player is in no game.
     */
    public boolean kickPlayer(final String playerID) throws RemoteException,
            IllegalStateException {
        if (this.getGame() == null) {
            throw new IllegalStateException("You are not in a gameLobby.");
        }
        if (this.getGame().isRunning()) {
            throw new IllegalStateException("Can't kick while game is running.");
        }
        if (!this.getID().equals(this.getGame().getGameOwner().getID())) {
            throw new IllegalStateException("You must be owner of game.");
        }
        if (!this.getGame().isPlayerInGame(playerID)) {
            throw new IllegalStateException("Player is not in game.");
        }
        if (this.getID().equals(playerID)) {
            throw new IllegalStateException("You can't kick yourself.");
        }

        RemotePlayer holder = Login.getPlayer(playerID);
        this.getGame().removePlayer(holder);
        holder.addCommand(new KickCmd(this.getID(), playerID));

        return true;
    }

    /**
     * Called by client to retrieve string of player id.
     * @return name of player
     * @throws java.rmi.RemoteException
     */
    public String getPlayerID() throws RemoteException {
        return this.getID();
    }

    /**
     * Called by client to gracefully leave gameLobby
     * @throws java.rmi.RemoteException throws RemoteException
     * @throws IllegalStateException If the player is in no game.
     */
    public void leaveGameLobby() throws RemoteException,
            IllegalStateException {
        if (this.getGame() == null) {
            throw new IllegalStateException("You are not in a gameLobby.");
        }
        if (this.getGame().isRunning()) {
            throw new IllegalStateException("Can't leave while game is running.");
        }

        Game currGame = this.getGame();
        List<RemotePlayer> deletedPlayers = new ArrayList<RemotePlayer>();
        if (currGame.getGameOwner().equals(this)) {
            for (RemotePlayer player : currGame.getPlayers()) {
                deletedPlayers.add(player);
                if (!this.equals(player)) {
                    player.addCommand(new KickCmd("Server",
                            player.getPlayerID(),
                            "Removed from game because owner of game left."));
                }
            }

            for (RemotePlayer player : deletedPlayers) {
                if (player.isReadyToInitialize()) {
                    currGame.unReady(player);
                }
                currGame.removePlayer(player);
            }

            currGame.close();
        } else {
            this.getGame().removePlayer(this);
        }
    }

    DataBase getDataBase() {
        return DataBase.get();
    }

    Ranking getRanking() {
        return Ranking.get(getID());
    }

    /**
     * Returns the own level
     * @return own level
     */
    public int getLevelRank() {
        return Coinsystem.getLevelForCoins(ranking.getCoins());
    }

    /**
     * Called by client to get his own amount of coins.
     * @return amount of coins
     * @throws java.rmi.RemoteException
     */
    public long getCoins() throws RemoteException {
        return ranking.getCoins();
    }

    /**
     * Returns all information about a saved robot. This method is used to
     * reseive information about robots befor a game until the GameInfo-
     * Object holds the whole RobotInfo about all robots. If the robot
     * is not found, it throws IllegalARgumentException
     * @param robotID ID of robot the client wants details about.
     * @return RobotInfo of desired robot.
     * @throws java.rmi.RemoteException
     * @throws IllegalArgumentException
     * @deprecated
     */
    public RobotInfo getRobotInfo(final int robotID) throws RemoteException,
            IllegalArgumentException {
        RobotConfiguration rC = DataBase.get().getRobot(robotID);
        if (rC == null) {
            throw new IllegalArgumentException("RobotConfigurtion with id " + robotID + " does not exist ");
        } else {
            return rC.getInfo();
        }
    }

    /**
     * Called by client to get a String List of available maps on server.
     * @return getMapInfos infos of a map
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public List<String> getMapInfos() throws RemoteException {
        return new ArrayList(GameMap.allMapInfos.keySet());
    }

    /**
     * Called by client to get a MapInfo Object containing info on a map.
     * @param mapName String representation of map name
     * @return getMapInfo info of a map.
     * @throws java.rmi.RemoteException throws RemoteException
     * @throws IllegalStateException If the player is in no game.
     */
    public MapInfo getMapInfo(final String mapName) throws RemoteException,
            IllegalArgumentException {

        MapInfo info = GameMap.allMapInfos.get(mapName);
        if (info == null) {
            throw new IllegalArgumentException(String.format("There is no map named" +
                    " %s!", mapName));
        } else {
            return info;
        }

    }

    /**
     * Called by client to set back to "not ready" when in a game lobby
     * @throws java.rmi.RemoteException throws RemoteException
     * @throws IllegalStateException If the player is in no game.
     */
    public void setUnReady() throws RemoteException, IllegalStateException {
        if (this.getGame() == null) {
            throw new IllegalStateException("You are not in a gameLobby.");
        }
        if (this.getGame().isInitializing()) {
            throw new IllegalStateException("Game is already initializing.");
        }
        if (this.getGame().isRunning()) {
            throw new IllegalStateException("Game is already running.");
        }

        this.readyToInitialize = false;
        this.getGame().unReady(this);

    }

    /**
     * Called by client to get the needed coins for a level
     * @param playerLevel level for which the amount of coins will be returned
     * @return amount of coins for a level
     * @throws java.rmi.RemoteException
     */
    public long getCoins(final int playerLeve) throws RemoteException {
        return Coinsystem.getCoinsForLevel(playerLeve);
    }

    private long getSessionTime() {
        return player.getSessionTime();
    }
}